home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / cmdlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  20.4 KB  |  1,181 lines

  1. // cmdlib.c
  2.  
  3. #include "cmdlib.h"
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6.  
  7. #ifdef WIN32
  8. #include <direct.h>
  9. #include <windows.h>
  10. #endif
  11.  
  12. #ifdef NeXT
  13. #include <libc.h>
  14. #endif
  15.  
  16. #define    BASEDIRNAME    "quake"        // assumed to have a 2 or 3 following
  17. #define PATHSEPERATOR   '/'
  18.  
  19. // set these before calling CheckParm
  20. int myargc;
  21. char **myargv;
  22.  
  23. char        com_token[1024];
  24. qboolean    com_eof;
  25.  
  26. qboolean        archive;
  27. char            archivedir[1024];
  28.  
  29.  
  30. /*
  31. ===================
  32. ExpandWildcards
  33.  
  34. Mimic unix command line expansion
  35. ===================
  36. */
  37. #define    MAX_EX_ARGC    1024
  38. int        ex_argc;
  39. char    *ex_argv[MAX_EX_ARGC];
  40. #ifdef _WIN32
  41. #include "io.h"
  42. void ExpandWildcards( int *argc, char ***argv )
  43. {
  44.     struct _finddata_t fileinfo;
  45.     int        handle;
  46.     int        i;
  47.     char    filename[1024];
  48.     char    filebase[1024];
  49.     char    *path;
  50.  
  51.     ex_argc = 0;
  52.     for (i=0 ; i<*argc ; i++)
  53.     {
  54.         path = (*argv)[i];
  55.         if ( path[0] == '-'
  56.             || ( !strstr(path, "*") && !strstr(path, "?") ) )
  57.         {
  58.             ex_argv[ex_argc++] = path;
  59.             continue;
  60.         }
  61.  
  62.         handle = _findfirst (path, &fileinfo);
  63.         if (handle == -1)
  64.             return;
  65.  
  66.         ExtractFilePath (path, filebase);
  67.  
  68.         do
  69.         {
  70.             sprintf (filename, "%s%s", filebase, fileinfo.name);
  71.             ex_argv[ex_argc++] = copystring (filename);
  72.         } while (_findnext( handle, &fileinfo ) != -1);
  73.  
  74.         _findclose (handle);
  75.     }
  76.  
  77.     *argc = ex_argc;
  78.     *argv = ex_argv;
  79. }
  80. #else
  81. void ExpandWildcards (int *argc, char ***argv)
  82. {
  83. }
  84. #endif
  85.  
  86. #ifdef WIN_ERROR
  87. #include <windows.h>
  88. /*
  89. =================
  90. Error
  91.  
  92. For abnormal program terminations in windowed apps
  93. =================
  94. */
  95. void Error( const char *error, ... )
  96. {
  97.     va_list argptr;
  98.     char    text[1024];
  99.     char    text2[1024];
  100.     int        err;
  101.  
  102.     err = GetLastError ();
  103.  
  104.     va_start (argptr,error);
  105.     vsprintf (text, error,argptr);
  106.     va_end (argptr);
  107.  
  108.     sprintf (text2, "%s\nGetLastError() = %i", text, err);
  109.     MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
  110.  
  111.     exit (1);
  112. }
  113.  
  114. #else
  115. /*
  116. =================
  117. Error
  118.  
  119. For abnormal program terminations in console apps
  120. =================
  121. */
  122. void Error( const char *error, ...)
  123. {
  124.     va_list argptr;
  125.  
  126.     _printf ("\n************ ERROR ************\n");
  127.  
  128.     va_start (argptr,error);
  129.     vprintf (error,argptr);
  130.     va_end (argptr);
  131.     _printf ("\r\n");
  132.  
  133.     exit (1);
  134. }
  135. #endif
  136.  
  137. // only printf if in verbose mode
  138. qboolean verbose = qfalse;
  139. void qprintf( const char *format, ... ) {
  140.     va_list argptr;
  141.  
  142.     if (!verbose)
  143.         return;
  144.  
  145.     va_start (argptr,format);
  146.     vprintf (format,argptr);
  147.     va_end (argptr);
  148.  
  149. }
  150.  
  151. #ifdef WIN32
  152. HWND hwndOut = NULL;
  153. qboolean lookedForServer = qfalse;
  154. UINT wm_BroadcastCommand = -1;
  155. #endif
  156.  
  157. void _printf( const char *format, ... ) {
  158.     va_list argptr;
  159.   char text[4096];
  160.   ATOM a;
  161.  
  162.     va_start (argptr,format);
  163.     vsprintf (text, format, argptr);
  164.     va_end (argptr);
  165.  
  166.   printf(text);
  167.  
  168. #ifdef WIN32
  169.   if (!lookedForServer) {
  170.     lookedForServer = qtrue;
  171.     hwndOut = FindWindow(NULL, "Q3Map Process Server");
  172.     if (hwndOut) {
  173.       wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" );
  174.     }
  175.   }
  176.   if (hwndOut) {
  177.     a = GlobalAddAtom(text);
  178.     PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a);
  179.   }
  180. #endif
  181. }
  182.  
  183.  
  184. /*
  185.  
  186. qdir will hold the path up to the quake directory, including the slash
  187.  
  188.   f:\quake\
  189.   /raid/quake/
  190.  
  191. gamedir will hold qdir + the game directory (id1, id2, etc)
  192.  
  193.   */
  194.  
  195. char        qdir[1024];
  196. char        gamedir[1024];
  197. char        writedir[1024];
  198.  
  199. void SetQdirFromPath( const char *path )
  200. {
  201.     char    temp[1024];
  202.     const char    *c;
  203.   const char *sep;
  204.     int        len, count;
  205.  
  206.     if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
  207.     {    // path is partial
  208.         Q_getwd (temp);
  209.         strcat (temp, path);
  210.         path = temp;
  211.     }
  212.  
  213.     // search for "quake2" in path
  214.  
  215.     len = strlen(BASEDIRNAME);
  216.     for (c=path+strlen(path)-1 ; c != path ; c--)
  217.     {
  218.         int i;
  219.  
  220.         if (!Q_strncasecmp (c, BASEDIRNAME, len))
  221.         {
  222.       //
  223.             //strncpy (qdir, path, c+len+2-path);
  224.       // the +2 assumes a 2 or 3 following quake which is not the
  225.       // case with a retail install
  226.       // so we need to add up how much to the next separator
  227.       sep = c + len;
  228.       count = 1;
  229.       while (*sep && *sep != '/' && *sep != '\\')
  230.       {
  231.         sep++;
  232.         count++;
  233.       }
  234.             strncpy (qdir, path, c+len+count-path);
  235.             qprintf ("qdir: %s\n", qdir);
  236.             for ( i = 0; i < strlen( qdir ); i++ )
  237.             {
  238.                 if ( qdir[i] == '\\' ) 
  239.                     qdir[i] = '/';
  240.             }
  241.  
  242.             c += len+count;
  243.             while (*c)
  244.             {
  245.                 if (*c == '/' || *c == '\\')
  246.                 {
  247.                     strncpy (gamedir, path, c+1-path);
  248.  
  249.                     for ( i = 0; i < strlen( gamedir ); i++ )
  250.                     {
  251.                         if ( gamedir[i] == '\\' ) 
  252.                             gamedir[i] = '/';
  253.                     }
  254.  
  255.                     qprintf ("gamedir: %s\n", gamedir);
  256.  
  257.                     if ( !writedir[0] )
  258.                         strcpy( writedir, gamedir );
  259.                     else if ( writedir[strlen( writedir )-1] != '/' )
  260.                     {
  261.                         writedir[strlen( writedir )] = '/';
  262.                         writedir[strlen( writedir )+1] = 0;
  263.                     }
  264.  
  265.                     return;
  266.                 }
  267.                 c++;
  268.             }
  269.             Error ("No gamedir in %s", path);
  270.             return;
  271.         }
  272.     }
  273.     Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
  274. }
  275.  
  276. char *ExpandArg (const char *path)
  277. {
  278.     static char full[1024];
  279.  
  280.     if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
  281.     {
  282.         Q_getwd (full);
  283.         strcat (full, path);
  284.     }
  285.     else
  286.         strcpy (full, path);
  287.     return full;
  288. }
  289.  
  290. char *ExpandPath (const char *path)
  291. {
  292.     static char full[1024];
  293.     if (!qdir)
  294.         Error ("ExpandPath called without qdir set");
  295.     if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
  296.         strcpy( full, path );
  297.         return full;
  298.     }
  299.     sprintf (full, "%s%s", qdir, path);
  300.     return full;
  301. }
  302.  
  303. char *ExpandGamePath (const char *path)
  304. {
  305.     static char full[1024];
  306.     if (!qdir)
  307.         Error ("ExpandGamePath called without qdir set");
  308.     if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
  309.         strcpy( full, path );
  310.         return full;
  311.     }
  312.     sprintf (full, "%s%s", gamedir, path);
  313.     return full;
  314. }
  315.  
  316. char *ExpandPathAndArchive (const char *path)
  317. {
  318.     char    *expanded;
  319.     char    archivename[1024];
  320.  
  321.     expanded = ExpandPath (path);
  322.  
  323.     if (archive)
  324.     {
  325.         sprintf (archivename, "%s/%s", archivedir, path);
  326.         QCopyFile (expanded, archivename);
  327.     }
  328.     return expanded;
  329. }
  330.  
  331.  
  332. char *copystring(const char *s)
  333. {
  334.     char    *b;
  335.     b = malloc(strlen(s)+1);
  336.     strcpy (b, s);
  337.     return b;
  338. }
  339.  
  340.  
  341.  
  342. /*
  343. ================
  344. I_FloatTime
  345. ================
  346. */
  347. double I_FloatTime (void)
  348. {
  349.     time_t    t;
  350.     
  351.     time (&t);
  352.     
  353.     return t;
  354. #if 0
  355. // more precise, less portable
  356.     struct timeval tp;
  357.     struct timezone tzp;
  358.     static int        secbase;
  359.  
  360.     gettimeofday(&tp, &tzp);
  361.     
  362.     if (!secbase)
  363.     {
  364.         secbase = tp.tv_sec;
  365.         return tp.tv_usec/1000000.0;
  366.     }
  367.     
  368.     return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
  369. #endif
  370. }
  371.  
  372. void Q_getwd (char *out)
  373. {
  374.     int i = 0;
  375.  
  376. #ifdef WIN32
  377.    _getcwd (out, 256);
  378.    strcat (out, "\\");
  379. #else
  380.    getwd (out);
  381.    strcat (out, "/");
  382. #endif
  383.  
  384.    while ( out[i] != 0 )
  385.    {
  386.        if ( out[i] == '\\' )
  387.            out[i] = '/';
  388.        i++;
  389.    }
  390. }
  391.  
  392.  
  393. void Q_mkdir (const char *path)
  394. {
  395. #ifdef WIN32
  396.     if (_mkdir (path) != -1)
  397.         return;
  398. #else
  399.     if (mkdir (path, 0777) != -1)
  400.         return;
  401. #endif
  402.     if (errno != EEXIST)
  403.         Error ("mkdir %s: %s",path, strerror(errno));
  404. }
  405.  
  406. /*
  407. ============
  408. FileTime
  409.  
  410. returns -1 if not present
  411. ============
  412. */
  413. int    FileTime (const char *path)
  414. {
  415.     struct    stat    buf;
  416.     
  417.     if (stat (path,&buf) == -1)
  418.         return -1;
  419.     
  420.     return buf.st_mtime;
  421. }
  422.  
  423.  
  424.  
  425. /*
  426. ==============
  427. COM_Parse
  428.  
  429. Parse a token out of a string
  430. ==============
  431. */
  432. char *COM_Parse (char *data)
  433. {
  434.     int        c;
  435.     int        len;
  436.     
  437.     len = 0;
  438.     com_token[0] = 0;
  439.     
  440.     if (!data)
  441.         return NULL;
  442.         
  443. // skip whitespace
  444. skipwhite:
  445.     while ( (c = *data) <= ' ')
  446.     {
  447.         if (c == 0)
  448.         {
  449.             com_eof = qtrue;
  450.             return NULL;            // end of file;
  451.         }
  452.         data++;
  453.     }
  454.     
  455. // skip // comments
  456.     if (c=='/' && data[1] == '/')
  457.     {
  458.         while (*data && *data != '\n')
  459.             data++;
  460.         goto skipwhite;
  461.     }
  462.     
  463.  
  464. // handle quoted strings specially
  465.     if (c == '\"')
  466.     {
  467.         data++;
  468.         do
  469.         {
  470.             c = *data++;
  471.             if (c=='\"')
  472.             {
  473.                 com_token[len] = 0;
  474.                 return data;
  475.             }
  476.             com_token[len] = c;
  477.             len++;
  478.         } while (1);
  479.     }
  480.  
  481. // parse single characters
  482.     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  483.     {
  484.         com_token[len] = c;
  485.         len++;
  486.         com_token[len] = 0;
  487.         return data+1;
  488.     }
  489.  
  490. // parse a regular word
  491.     do
  492.     {
  493.         com_token[len] = c;
  494.         data++;
  495.         len++;
  496.         c = *data;
  497.     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  498.             break;
  499.     } while (c>32);
  500.     
  501.     com_token[len] = 0;
  502.     return data;
  503. }
  504.  
  505.  
  506. int Q_strncasecmp (const char *s1, const char *s2, int n)
  507. {
  508.     int        c1, c2;
  509.     
  510.     do
  511.     {
  512.         c1 = *s1++;
  513.         c2 = *s2++;
  514.  
  515.         if (!n--)
  516.             return 0;        // strings are equal until end point
  517.         
  518.         if (c1 != c2)
  519.         {
  520.             if (c1 >= 'a' && c1 <= 'z')
  521.                 c1 -= ('a' - 'A');
  522.             if (c2 >= 'a' && c2 <= 'z')
  523.                 c2 -= ('a' - 'A');
  524.             if (c1 != c2)
  525.                 return -1;        // strings not equal
  526.         }
  527.     } while (c1);
  528.     
  529.     return 0;        // strings are equal
  530. }
  531.  
  532. int Q_stricmp (const char *s1, const char *s2)
  533. {
  534.     return Q_strncasecmp (s1, s2, 99999);
  535. }
  536.  
  537.  
  538. char *strupr (char *start)
  539. {
  540.     char    *in;
  541.     in = start;
  542.     while (*in)
  543.     {
  544.         *in = toupper(*in);
  545.         in++;
  546.     }
  547.     return start;
  548. }
  549.  
  550. char *strlower (char *start)
  551. {
  552.     char    *in;
  553.     in = start;
  554.     while (*in)
  555.     {
  556.         *in = tolower(*in); 
  557.         in++;
  558.     }
  559.     return start;
  560. }
  561.  
  562.  
  563. /*
  564. =============================================================================
  565.  
  566.                         MISC FUNCTIONS
  567.  
  568. =============================================================================
  569. */
  570.  
  571.  
  572. /*
  573. =================
  574. CheckParm
  575.  
  576. Checks for the given parameter in the program's command line arguments
  577. Returns the argument number (1 to argc-1) or 0 if not present
  578. =================
  579. */
  580. int CheckParm (const char *check)
  581. {
  582.     int             i;
  583.  
  584.     for (i = 1;i<myargc;i++)
  585.     {
  586.         if ( !Q_stricmp(check, myargv[i]) )
  587.             return i;
  588.     }
  589.  
  590.     return 0;
  591. }
  592.  
  593.  
  594.  
  595. /*
  596. ================
  597. Q_filelength
  598. ================
  599. */
  600. int Q_filelength (FILE *f)
  601. {
  602.     int        pos;
  603.     int        end;
  604.  
  605.     pos = ftell (f);
  606.     fseek (f, 0, SEEK_END);
  607.     end = ftell (f);
  608.     fseek (f, pos, SEEK_SET);
  609.  
  610.     return end;
  611. }
  612.  
  613.  
  614. FILE *SafeOpenWrite (const char *filename)
  615. {
  616.     FILE    *f;
  617.  
  618.     f = fopen(filename, "wb");
  619.  
  620.     if (!f)
  621.         Error ("Error opening %s: %s",filename,strerror(errno));
  622.  
  623.     return f;
  624. }
  625.  
  626. FILE *SafeOpenRead (const char *filename)
  627. {
  628.     FILE    *f;
  629.  
  630.     f = fopen(filename, "rb");
  631.  
  632.     if (!f)
  633.         Error ("Error opening %s: %s",filename,strerror(errno));
  634.  
  635.     return f;
  636. }
  637.  
  638.  
  639. void SafeRead (FILE *f, void *buffer, int count)
  640. {
  641.     if ( fread (buffer, 1, count, f) != (size_t)count)
  642.         Error ("File read failure");
  643. }
  644.  
  645.  
  646. void SafeWrite (FILE *f, const void *buffer, int count)
  647. {
  648.     if (fwrite (buffer, 1, count, f) != (size_t)count)
  649.         Error ("File write failure");
  650. }
  651.  
  652.  
  653. /*
  654. ==============
  655. FileExists
  656. ==============
  657. */
  658. qboolean    FileExists (const char *filename)
  659. {
  660.     FILE    *f;
  661.  
  662.     f = fopen (filename, "r");
  663.     if (!f)
  664.         return qfalse;
  665.     fclose (f);
  666.     return qtrue;
  667. }
  668.  
  669. /*
  670. ==============
  671. LoadFile
  672. ==============
  673. */
  674. int    LoadFile( const char *filename, void **bufferptr )
  675. {
  676.     FILE    *f;
  677.     int    length;
  678.     void    *buffer;
  679.  
  680.     f = SafeOpenRead (filename);
  681.     length = Q_filelength (f);
  682.     buffer = malloc (length+1);
  683.     ((char *)buffer)[length] = 0;
  684.     SafeRead (f, buffer, length);
  685.     fclose (f);
  686.  
  687.     *bufferptr = buffer;
  688.     return length;
  689. }
  690.  
  691.  
  692. /*
  693. ==============
  694. LoadFileBlock
  695. -
  696. rounds up memory allocation to 4K boundry
  697. -
  698. ==============
  699. */
  700. int    LoadFileBlock( const char *filename, void **bufferptr )
  701. {
  702.     FILE    *f;
  703.     int    length, nBlock, nAllocSize;
  704.     void    *buffer;
  705.  
  706.     f = SafeOpenRead (filename);
  707.     length = Q_filelength (f);
  708.   nAllocSize = length;
  709.   nBlock = nAllocSize % MEM_BLOCKSIZE;
  710.   if ( nBlock > 0) {
  711.     nAllocSize += MEM_BLOCKSIZE - nBlock;
  712.   }
  713.     buffer = malloc (nAllocSize+1);
  714.   memset(buffer, 0, nAllocSize+1);
  715.     SafeRead (f, buffer, length);
  716.     fclose (f);
  717.  
  718.     *bufferptr = buffer;
  719.     return length;
  720. }
  721.  
  722.  
  723. /*
  724. ==============
  725. TryLoadFile
  726.  
  727. Allows failure
  728. ==============
  729. */
  730. int    TryLoadFile (const char *filename, void **bufferptr)
  731. {
  732.     FILE    *f;
  733.     int    length;
  734.     void    *buffer;
  735.  
  736.     *bufferptr = NULL;
  737.  
  738.     f = fopen (filename, "rb");
  739.     if (!f)
  740.         return -1;
  741.     length = Q_filelength (f);
  742.     buffer = malloc (length+1);
  743.     ((char *)buffer)[length] = 0;
  744.     SafeRead (f, buffer, length);
  745.     fclose (f);
  746.  
  747.     *bufferptr = buffer;
  748.     return length;
  749. }
  750.  
  751.  
  752. /*
  753. ==============
  754. SaveFile
  755. ==============
  756. */
  757. void    SaveFile (const char *filename, const void *buffer, int count)
  758. {
  759.     FILE    *f;
  760.  
  761.     f = SafeOpenWrite (filename);
  762.     SafeWrite (f, buffer, count);
  763.     fclose (f);
  764. }
  765.  
  766.  
  767.  
  768. void DefaultExtension (char *path, const char *extension)
  769. {
  770.     char    *src;
  771. //
  772. // if path doesnt have a .EXT, append extension
  773. // (extension should include the .)
  774. //
  775.     src = path + strlen(path) - 1;
  776.  
  777.     while (*src != '/' && *src != '\\' && src != path)
  778.     {
  779.         if (*src == '.')
  780.             return;                 // it has an extension
  781.         src--;
  782.     }
  783.  
  784.     strcat (path, extension);
  785. }
  786.  
  787.  
  788. void DefaultPath (char *path, const char *basepath)
  789. {
  790.     char    temp[128];
  791.  
  792.     if (path[0] == PATHSEPERATOR)
  793.         return;                   // absolute path location
  794.     strcpy (temp,path);
  795.     strcpy (path,basepath);
  796.     strcat (path,temp);
  797. }
  798.  
  799.  
  800. void    StripFilename (char *path)
  801. {
  802.     int             length;
  803.  
  804.     length = strlen(path)-1;
  805.     while (length > 0 && path[length] != PATHSEPERATOR)
  806.         length--;
  807.     path[length] = 0;
  808. }
  809.  
  810. void    StripExtension (char *path)
  811. {
  812.     int             length;
  813.  
  814.     length = strlen(path)-1;
  815.     while (length > 0 && path[length] != '.')
  816.     {
  817.         length--;
  818.         if (path[length] == '/')
  819.             return;        // no extension
  820.     }
  821.     if (length)
  822.         path[length] = 0;
  823. }
  824.  
  825.  
  826. /*
  827. ====================
  828. Extract file parts
  829. ====================
  830. */
  831. // FIXME: should include the slash, otherwise
  832. // backing to an empty path will be wrong when appending a slash
  833. void ExtractFilePath (const char *path, char *dest)
  834. {
  835.     const char    *src;
  836.  
  837.     src = path + strlen(path) - 1;
  838.  
  839. //
  840. // back up until a \ or the start
  841. //
  842.     while (src != path && *(src-1) != '\\' && *(src-1) != '/')
  843.         src--;
  844.  
  845.     memcpy (dest, path, src-path);
  846.     dest[src-path] = 0;
  847. }
  848.  
  849. void ExtractFileBase (const char *path, char *dest)
  850. {
  851.     const char    *src;
  852.  
  853.     src = path + strlen(path) - 1;
  854.  
  855. //
  856. // back up until a \ or the start
  857. //
  858.     while (src != path && *(src-1) != PATHSEPERATOR)
  859.         src--;
  860.  
  861.     while (*src && *src != '.')
  862.     {
  863.         *dest++ = *src++;
  864.     }
  865.     *dest = 0;
  866. }
  867.  
  868. void ExtractFileExtension (const char *path, char *dest)
  869. {
  870.     const char    *src;
  871.  
  872.     src = path + strlen(path) - 1;
  873.  
  874. //
  875. // back up until a . or the start
  876. //
  877.     while (src != path && *(src-1) != '.')
  878.         src--;
  879.     if (src == path)
  880.     {
  881.         *dest = 0;    // no extension
  882.         return;
  883.     }
  884.  
  885.     strcpy (dest,src);
  886. }
  887.  
  888.  
  889. /*
  890. ==============
  891. ParseNum / ParseHex
  892. ==============
  893. */
  894. int ParseHex (const char *hex)
  895. {
  896.     const char    *str;
  897.     int    num;
  898.  
  899.     num = 0;
  900.     str = hex;
  901.  
  902.     while (*str)
  903.     {
  904.         num <<= 4;
  905.         if (*str >= '0' && *str <= '9')
  906.             num += *str-'0';
  907.         else if (*str >= 'a' && *str <= 'f')
  908.             num += 10 + *str-'a';
  909.         else if (*str >= 'A' && *str <= 'F')
  910.             num += 10 + *str-'A';
  911.         else
  912.             Error ("Bad hex number: %s",hex);
  913.         str++;
  914.     }
  915.  
  916.     return num;
  917. }
  918.  
  919.  
  920. int ParseNum (const char *str)
  921. {
  922.     if (str[0] == '$')
  923.         return ParseHex (str+1);
  924.     if (str[0] == '0' && str[1] == 'x')
  925.         return ParseHex (str+2);
  926.     return atol (str);
  927. }
  928.  
  929.  
  930.  
  931. /*
  932. ============================================================================
  933.  
  934.                     BYTE ORDER FUNCTIONS
  935.  
  936. ============================================================================
  937. */
  938.  
  939. #ifdef _SGI_SOURCE
  940. #define    __BIG_ENDIAN__
  941. #endif
  942.  
  943. #ifdef __BIG_ENDIAN__
  944.  
  945. short   LittleShort (short l)
  946. {
  947.     byte    b1,b2;
  948.  
  949.     b1 = l&255;
  950.     b2 = (l>>8)&255;
  951.  
  952.     return (b1<<8) + b2;
  953. }
  954.  
  955. short   BigShort (short l)
  956. {
  957.     return l;
  958. }
  959.  
  960.  
  961. int    LittleLong (int l)
  962. {
  963.     byte    b1,b2,b3,b4;
  964.  
  965.     b1 = l&255;
  966.     b2 = (l>>8)&255;
  967.     b3 = (l>>16)&255;
  968.     b4 = (l>>24)&255;
  969.  
  970.     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  971. }
  972.  
  973. int    BigLong (int l)
  974. {
  975.     return l;
  976. }
  977.  
  978.  
  979. float    LittleFloat (float l)
  980. {
  981.     union {byte b[4]; float f;} in, out;
  982.     
  983.     in.f = l;
  984.     out.b[0] = in.b[3];
  985.     out.b[1] = in.b[2];
  986.     out.b[2] = in.b[1];
  987.     out.b[3] = in.b[0];
  988.     
  989.     return out.f;
  990. }
  991.  
  992. float    BigFloat (float l)
  993. {
  994.     return l;
  995. }
  996.  
  997.  
  998. #else
  999.  
  1000.  
  1001. short   BigShort (short l)
  1002. {
  1003.     byte    b1,b2;
  1004.  
  1005.     b1 = l&255;
  1006.     b2 = (l>>8)&255;
  1007.  
  1008.     return (b1<<8) + b2;
  1009. }
  1010.  
  1011. short   LittleShort (short l)
  1012. {
  1013.     return l;
  1014. }
  1015.  
  1016.  
  1017. int    BigLong (int l)
  1018. {
  1019.     byte    b1,b2,b3,b4;
  1020.  
  1021.     b1 = l&255;
  1022.     b2 = (l>>8)&255;
  1023.     b3 = (l>>16)&255;
  1024.     b4 = (l>>24)&255;
  1025.  
  1026.     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  1027. }
  1028.  
  1029. int    LittleLong (int l)
  1030. {
  1031.     return l;
  1032. }
  1033.  
  1034. float    BigFloat (float l)
  1035. {
  1036.     union {byte b[4]; float f;} in, out;
  1037.     
  1038.     in.f = l;
  1039.     out.b[0] = in.b[3];
  1040.     out.b[1] = in.b[2];
  1041.     out.b[2] = in.b[1];
  1042.     out.b[3] = in.b[0];
  1043.     
  1044.     return out.f;
  1045. }
  1046.  
  1047. float    LittleFloat (float l)
  1048. {
  1049.     return l;
  1050. }
  1051.  
  1052.  
  1053. #endif
  1054.  
  1055.  
  1056. //=======================================================
  1057.  
  1058.  
  1059. // FIXME: byte swap?
  1060.  
  1061. // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
  1062. // and the initial and final xor values shown below...  in other words, the
  1063. // CCITT standard CRC used by XMODEM
  1064.  
  1065. #define CRC_INIT_VALUE    0xffff
  1066. #define CRC_XOR_VALUE    0x0000
  1067.  
  1068. static unsigned short crctable[256] =
  1069. {
  1070.     0x0000,    0x1021,    0x2042,    0x3063,    0x4084,    0x50a5,    0x60c6,    0x70e7,
  1071.     0x8108,    0x9129,    0xa14a,    0xb16b,    0xc18c,    0xd1ad,    0xe1ce,    0xf1ef,
  1072.     0x1231,    0x0210,    0x3273,    0x2252,    0x52b5,    0x4294,    0x72f7,    0x62d6,
  1073.     0x9339,    0x8318,    0xb37b,    0xa35a,    0xd3bd,    0xc39c,    0xf3ff,    0xe3de,
  1074.     0x2462,    0x3443,    0x0420,    0x1401,    0x64e6,    0x74c7,    0x44a4,    0x5485,
  1075.     0xa56a,    0xb54b,    0x8528,    0x9509,    0xe5ee,    0xf5cf,    0xc5ac,    0xd58d,
  1076.     0x3653,    0x2672,    0x1611,    0x0630,    0x76d7,    0x66f6,    0x5695,    0x46b4,
  1077.     0xb75b,    0xa77a,    0x9719,    0x8738,    0xf7df,    0xe7fe,    0xd79d,    0xc7bc,
  1078.     0x48c4,    0x58e5,    0x6886,    0x78a7,    0x0840,    0x1861,    0x2802,    0x3823,
  1079.     0xc9cc,    0xd9ed,    0xe98e,    0xf9af,    0x8948,    0x9969,    0xa90a,    0xb92b,
  1080.     0x5af5,    0x4ad4,    0x7ab7,    0x6a96,    0x1a71,    0x0a50,    0x3a33,    0x2a12,
  1081.     0xdbfd,    0xcbdc,    0xfbbf,    0xeb9e,    0x9b79,    0x8b58,    0xbb3b,    0xab1a,
  1082.     0x6ca6,    0x7c87,    0x4ce4,    0x5cc5,    0x2c22,    0x3c03,    0x0c60,    0x1c41,
  1083.     0xedae,    0xfd8f,    0xcdec,    0xddcd,    0xad2a,    0xbd0b,    0x8d68,    0x9d49,
  1084.     0x7e97,    0x6eb6,    0x5ed5,    0x4ef4,    0x3e13,    0x2e32,    0x1e51,    0x0e70,
  1085.     0xff9f,    0xefbe,    0xdfdd,    0xcffc,    0xbf1b,    0xaf3a,    0x9f59,    0x8f78,
  1086.     0x9188,    0x81a9,    0xb1ca,    0xa1eb,    0xd10c,    0xc12d,    0xf14e,    0xe16f,
  1087.     0x1080,    0x00a1,    0x30c2,    0x20e3,    0x5004,    0x4025,    0x7046,    0x6067,
  1088.     0x83b9,    0x9398,    0xa3fb,    0xb3da,    0xc33d,    0xd31c,    0xe37f,    0xf35e,
  1089.     0x02b1,    0x1290,    0x22f3,    0x32d2,    0x4235,    0x5214,    0x6277,    0x7256,
  1090.     0xb5ea,    0xa5cb,    0x95a8,    0x8589,    0xf56e,    0xe54f,    0xd52c,    0xc50d,
  1091.     0x34e2,    0x24c3,    0x14a0,    0x0481,    0x7466,    0x6447,    0x5424,    0x4405,
  1092.     0xa7db,    0xb7fa,    0x8799,    0x97b8,    0xe75f,    0xf77e,    0xc71d,    0xd73c,
  1093.     0x26d3,    0x36f2,    0x0691,    0x16b0,    0x6657,    0x7676,    0x4615,    0x5634,
  1094.     0xd94c,    0xc96d,    0xf90e,    0xe92f,    0x99c8,    0x89e9,    0xb98a,    0xa9ab,
  1095.     0x5844,    0x4865,    0x7806,    0x6827,    0x18c0,    0x08e1,    0x3882,    0x28a3,
  1096.     0xcb7d,    0xdb5c,    0xeb3f,    0xfb1e,    0x8bf9,    0x9bd8,    0xabbb,    0xbb9a,
  1097.     0x4a75,    0x5a54,    0x6a37,    0x7a16,    0x0af1,    0x1ad0,    0x2ab3,    0x3a92,
  1098.     0xfd2e,    0xed0f,    0xdd6c,    0xcd4d,    0xbdaa,    0xad8b,    0x9de8,    0x8dc9,
  1099.     0x7c26,    0x6c07,    0x5c64,    0x4c45,    0x3ca2,    0x2c83,    0x1ce0,    0x0cc1,
  1100.     0xef1f,    0xff3e,    0xcf5d,    0xdf7c,    0xaf9b,    0xbfba,    0x8fd9,    0x9ff8,
  1101.     0x6e17,    0x7e36,    0x4e55,    0x5e74,    0x2e93,    0x3eb2,    0x0ed1,    0x1ef0
  1102. };
  1103.  
  1104. void CRC_Init(unsigned short *crcvalue)
  1105. {
  1106.     *crcvalue = CRC_INIT_VALUE;
  1107. }
  1108.  
  1109. void CRC_ProcessByte(unsigned short *crcvalue, byte data)
  1110. {
  1111.     *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
  1112. }
  1113.  
  1114. unsigned short CRC_Value(unsigned short crcvalue)
  1115. {
  1116.     return crcvalue ^ CRC_XOR_VALUE;
  1117. }
  1118. //=============================================================================
  1119.  
  1120. /*
  1121. ============
  1122. CreatePath
  1123. ============
  1124. */
  1125. void    CreatePath (const char *path)
  1126. {
  1127.     const char    *ofs;
  1128.     char        c;
  1129.     char        dir[1024];
  1130.  
  1131. #ifdef _WIN32
  1132.     int        olddrive = -1;
  1133.  
  1134.     if ( path[1] == ':' )
  1135.     {
  1136.         olddrive = _getdrive();
  1137.         _chdrive( toupper( path[0] ) - 'A' + 1 );
  1138.     }
  1139. #endif
  1140.  
  1141.     if (path[1] == ':')
  1142.         path += 2;
  1143.  
  1144.     for (ofs = path+1 ; *ofs ; ofs++)
  1145.     {
  1146.         c = *ofs;
  1147.         if (c == '/' || c == '\\')
  1148.         {    // create the directory
  1149.             memcpy( dir, path, ofs - path );
  1150.             dir[ ofs - path ] = 0;
  1151.             Q_mkdir( dir );
  1152.         }
  1153.     }
  1154.  
  1155. #ifdef _WIN32
  1156.     if ( olddrive != -1 )
  1157.     {
  1158.         _chdrive( olddrive );
  1159.     }
  1160. #endif
  1161. }
  1162.  
  1163.  
  1164. /*
  1165. ============
  1166. QCopyFile
  1167.  
  1168.   Used to archive source files
  1169. ============
  1170. */
  1171. void QCopyFile (const char *from, const char *to)
  1172. {
  1173.     void    *buffer;
  1174.     int        length;
  1175.  
  1176.     length = LoadFile (from, &buffer);
  1177.     CreatePath (to);
  1178.     SaveFile (to, buffer, length);
  1179.     free (buffer);
  1180. }
  1181.